package com.easystore.orm.pool
{
import com.easystore.orm.EasyStoreProperties;
import com.easystore.orm.utilities.CheckUtil;

import flash.data.SQLConnection;
import flash.errors.IllegalOperationError;
import flash.events.IOErrorEvent;
import flash.events.SQLErrorEvent;
import flash.filesystem.File;
import flash.utils.Dictionary;

import mx.controls.Alert;
import mx.utils.StringUtil;
	
public class ConnectionPool
{
	private static var __instance : ConnectionPool;
	
	private var __connections : Dictionary = new Dictionary(true);
	
	public function ConnectionPool(internalClass : Internal) 
	{
		CheckUtil.checkNotNull(internalClass,"internalClass", "ConnectionPool.<constructor>" );
	}
	
	public static function getInstance() : ConnectionPool 
	{
		if (__instance == null ) __instance = new ConnectionPool(new Internal());
		return __instance;
	}
	
	public function acquireSyncConnection() : SQLConnection {
		var databaseName : String = EasyStoreProperties.getInstance().getProperty(EasyStoreProperties.DB_FILE_NAME);
		CheckUtil.checkNotNull(databaseName,"databaseName", "ConnectionPool.acquire" );
		var sqlConnection : SQLConnection = null;
		var pool : Array = __connections[databaseName] as Array ;
		if ( pool != null ) {
			 var size  : int = pool.length;
              if (size > 0)
              	sqlConnection = SQLConnection(pool.shift());
		} else {
			sqlConnection = new SQLConnection(true);
		}
		sqlConnection.open( getFile(databaseName), getAutoCreate() );
		return sqlConnection;
	}
	
	public function acquireAsyncConnection(faultCallback : Function) : SQLConnection {
		var databaseName : String = EasyStoreProperties.getInstance().getProperty(EasyStoreProperties.DB_FILE_NAME);
		CheckUtil.checkNotNull(databaseName,"databaseName", "ConnectionPool.acquire" );
		var sqlConnection : SQLConnection = null;
		var pool : Array = __connections[databaseName] as Array ;
		if ( pool != null ) {
			 var size  : int = pool.length;
              if (size > 0)
              	sqlConnection = SQLConnection(pool.shift());
		} else {
			sqlConnection = new SQLConnection(false);
		}
		sqlConnection.addEventListener(SQLErrorEvent.ERROR, faultCallback );
		sqlConnection.addEventListener(IOErrorEvent.IO_ERROR, faultCallback );
		sqlConnection.open( getFile(databaseName), getAutoCreate() );
		return sqlConnection;
		
	}
	
	public function releaseConnection(sqlConnection : SQLConnection, faultCallback : Function) : void {
		var databaseName : String = sqlConnection.getFile().name;
		var pool : Array = __connections[databaseName] as Array ;
		if ( pool == null ) {
			pool = new Array();
			__connections[databaseName] = pool;
		} else {
			var maxPoolSize : int = int ( EasyStoreProperties.getInstance().getProperty(EasyStoreProperties.MAX_POOL_SIZE) );
			while  (pool.length >= maxPoolSize ) {
				pool.pop();
			}
		}
		pool.push(sqlConnection);
		sqlConnection.close();
		if ( !sqlConnection.synchronous && faultCallback != null ) {
			sqlConnection.removeEventListener(SQLErrorEvent.ERROR, faultCallback);
			sqlConnection.removeEventListener(IOErrorEvent.IO_ERROR , faultCallback);
		}
	}
	
	
	private function getFile(databaseName : String): File {		
		var filePath : String = StringUtil.trim(EasyStoreProperties.getInstance().getProperty(EasyStoreProperties.DB_FILE_DIRECTORY));
		var file : File;
		switch( filePath ) {
			case "applicationResourceDirectory":
				file = File.applicationResourceDirectory.resolvePath(databaseName);
			break;
			case "applicationStorageDirectory":
				file = File.applicationStorageDirectory.resolvePath(databaseName);
			break;
			case "documentsDirectory":
				file = File.documentsDirectory.resolvePath(databaseName);
			break;
			case "userDirectory":
				file = File.userDirectory.resolvePath(databaseName);
			break;
			default:
		} 
		if ( file == null ) throw new IllegalOperationError("unknown file path");
		return file;
	}
	
	private function getAutoCreate(): Boolean {
		var autoCreate : String =  StringUtil.trim(EasyStoreProperties.getInstance().getProperty(EasyStoreProperties.AUTO_CREATE_DB));
		return autoCreate == null ? true : ( autoCreate == "true" ? true : false);
	}
}
}
class Internal {}